package com.touka.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.touka.common.Result;
import com.touka.entity.Category;
import com.touka.entity.Dish;
import com.touka.entity.DishFlavor;
import com.touka.mapper.DishFlavorMapper;
import com.touka.service.CategoryService;
import com.touka.service.DishFlavorService;
import com.touka.service.DishService;
import com.touka.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {
  @Autowired
  private DishService dishService;
  @Autowired
  private DishFlavorService dishFlavorService;
  @Autowired
  private DishFlavorMapper dishFlavorMapper;
  @Autowired
  private CategoryService categoryService;
  @Autowired
  private AliOSSUtils aliOSSUtils;

  @Autowired
  private RedisTemplate redisTemplate;

  /**
   * 分页查询菜品
   *
   * @param page
   * @param pageSize
   * @return
   */
  @GetMapping("/page")
  @Cacheable(value = "dishCache", key = "#name + '_' + #page + '_' + #pageSize", unless = "#result == null")
  public Result<Map<String, Object>> list(String name, @DefaultValue("1") Long page, @DefaultValue("10") Long pageSize) {
    log.info("分页查询菜品：{}", name);
    Page<Dish> pageDish = new Page<>(page, pageSize);

    Page<Dish> dishPage = dishService.page(
            pageDish,
            Wrappers.lambdaQuery(Dish.class)
                    .like(StringUtils.isNotBlank(name), Dish::getName, name)
                    .orderByDesc(Dish::getCreateTime)
    );
    
    List<Dish> list = dishPage.getRecords().stream().map(dish -> {
      Category category = categoryService.getById(dish.getCategoryId());
      if (category != null) dish.setCategoryName(category.getName());
      return dish;
    }).toList();

    Map<String, Object> map = new HashMap<>();
    map.put("records", list);
    map.put("total", dishPage.getTotal());
    return Result.success(map);
  }

  /**
   * 新增菜品
   *
   * @param dish
   * @return
   */
  @PostMapping
  @Transactional // 事务管理
  @CacheEvict(value = "dishCache", allEntries = true) // 清除某个dishCache缓存
  public Result<String> insert(Dish dish) throws IOException {
    log.info("新增菜品：{}", dish);
    List<DishFlavor> lists = JSON.parseArray(dish.getDishFlavors(), DishFlavor.class);
    log.info("dishFlavors，{}", lists);

    if (dish.getFile() != null) {
      String url = aliOSSUtils.upload(dish.getFile());
      dish.setImage(url);
    }
    boolean save = dishService.saveOrUpdate(dish);
    if (save) {
      Long dishId = dish.getId();
      // 先删除口味信息
      dishFlavorService.remove(Wrappers.lambdaQuery(DishFlavor.class).eq(DishFlavor::getDishId, dishId));

      boolean saveBatch = dishFlavorService.saveOrUpdateBatch(lists.stream().map(dishFlavor -> {
        dishFlavor.setDishId(dishId);
        return dishFlavor;
      }).toList());
      if (saveBatch) {

        // 清理某个分类下面的菜品缓存数据
        // String key = "dish_" + dish.getCategoryId();
        // redisTemplate.delete(key);

        return Result.success("操作成功");
      }
    }
    return Result.error("添加失败");
  }

  /**
   * 根据Id查询菜品
   *
   * @param id
   * @return
   */
  @GetMapping("/{id}")
  public Result<Dish> getById(@PathVariable Long id) {
    log.info("dishId：{}", id);
    Dish dish = dishService.getById(id);
    List<DishFlavor> dishFlavors = dishFlavorMapper.selectList(Wrappers.lambdaQuery(DishFlavor.class).eq(DishFlavor::getDishId, id));
    dish.setFlavors(dishFlavors);
    return Result.success(dish);
  }

  /**
   * 停售/起售 0:停售  1:起售
   *
   * @param status
   * @param ids
   * @return
   */
  @PostMapping("/status/{status}")
  @CacheEvict(value = "dishCache", allEntries = true)
  public Result<String> status(@PathVariable Integer status, @RequestParam List<Long> ids) {
    log.info("停售/起售：{},{}", status, ids);

    boolean update = dishService.update(
            Wrappers.lambdaUpdate(Dish.class)
                    .in(Dish::getId, ids)
                    .set(Dish::getStatus, status)
    );

    return update ? Result.success("操作成功") : Result.error("操作失败");
  }

  /**
   * 删除/批量删除
   *
   * @param ids
   * @return
   */
  @DeleteMapping
  @CacheEvict(value = "dishCache", allEntries = true) // 清除所有dishCache缓存
  public Result<String> deleteByIds(@RequestParam List<Long> ids) {
    log.info("删除：{}", ids);
    boolean remove = dishService.removeByIds(ids);
    return remove ? Result.success("操作成功") : Result.error("操作失败");
  }

  /**
   * 根据分类Id或者名字获取菜品
   *
   * @param categoryId
   * @return
   */
  @GetMapping("/list")
  @Cacheable(value = "dishCache", key = "#categoryId", unless = "#result == null")
  public Result<List<Dish>> getDishByCategoryId(Long categoryId, String name) {
    log.info("根据分类Id或者名字获取菜品：{}-{}", categoryId, name);

    // 动态构造key
    // String key = "dish_" + categoryId;

    // 先从redis中获取缓存数据
    // List<Dish> redisDishList = (List<Dish>) redisTemplate.opsForValue().get(key);

    // if (!CollectionUtils.isEmpty(redisDishList)) {
    //    // 如果存在，直接返回，无序查询数据库
    //    return Result.success(redisDishList);
    //  }

    List<Dish> dishList = dishService.list(
            Wrappers.lambdaQuery(Dish.class)
                    .eq(categoryId != null, Dish::getCategoryId, categoryId)
                    .eq(Dish::getStatus, 1)
                    .like(StringUtils.isNotBlank(name), Dish::getName, name)
                    .orderByAsc(Dish::getSort)
                    .orderByDesc(Dish::getUpdateTime)
    );
    dishList.forEach(dish -> {
      List<DishFlavor> dishFlavors = dishFlavorService.list(
              Wrappers.lambdaQuery(DishFlavor.class).eq(DishFlavor::getDishId, dish.getId())
      );
      dish.setFlavors(dishFlavors);
    });

    // 如果查询数据库成功，缓存数据到redis数据库
    // redisTemplate.opsForValue().set(key, dishList, 60, TimeUnit.MINUTES);

    return Result.success(dishList);
  }
}
